/*
 * Circular buffer implementation.
 * If the circular buffer is filled beyond its capacity, it
 * automatically increases in size. This may cause reallocation
 * of memory which invalidates pointers into the buffer.
 * The circular buffer may also be abused as an auto-expanding array.
 */

#ifndef CBUF_H_
#define CBUF_H_

#include <stdbool.h>

typedef struct
{
	void* mem;
	int capacity;  // in # of elems
	int elem_size; // sizeof one elem
	int count;     // # of elems in Cbuf
	void* begin;
	void* end;
} Cbuf;

void cbuf_init (Cbuf* cbuf, int elem_size, int initial_capacity);
void cbuf_cleanup (Cbuf* cbuf);
void cbuf_push (Cbuf* cbuf, void* elem);
void* cbuf_pop (Cbuf* cbuf);
void* cbuf_elem (Cbuf* cbuf, int index);
bool cbuf_full (Cbuf* cbuf);
void cbuf_clear (Cbuf* cbuf);

#define CBUF_POP(CBUF,TYPE) ((TYPE*)cbuf_pop((CBUF)))
#define CBUF_ELEM(CBUF,INDEX,TYPE) ((TYPE*)cbuf_elem((CBUF),(INDEX)))
#define CBUF_HEAD(CBUF,TYPE) (TYPE*) cbuf_elem ((CBUF), (CBUF)->count-1)

#endif
